from PyQt5.QtWidgets import (QWidget, QVBoxLayout, QLabel, QLineEdit, 
                           QComboBox, QHBoxLayout, QTreeWidget, QGroupBox, 
                           QGridLayout, QDateTimeEdit, QRadioButton, QButtonGroup,
                           QPushButton, QTreeWidgetItem, QMessageBox)
from PyQt5.QtCore import QDate, Qt, QThread, pyqtSignal, QMetaObject, Q_ARG, QTimer
from core.platform_auth import platform_auth
from core.platform_config import platform_config
import aiohttp
from typing import List, Dict, Optional, Tuple
from dataclasses import dataclass
from datetime import datetime
from loguru import logger
import asyncio
import threading
import re
from qasync import asyncSlot
from nav.rfid_helper import RFIDHelper

@dataclass
class PersonIdentity:
    id: int 
    name: str
    description: str
    valid_flag: str

@dataclass
class Department:
    id: int
    parent_id: int
    name: str
    name_ext: str
    check_stat: int
    sort: int
    is_parent: int
    parent_ids: Optional[str] = None
    node_type: Optional[int] = None

class PersonApi:
    def __init__(self):
        self.base_url = f"{platform_config.dahua.api_host}/evo-apigw"
        
    async def get_person_identities(self) -> List[PersonIdentity]:
        """获取人员身份列表"""
        try:
            headers = await platform_auth.get_dahua_headers()
            async with aiohttp.ClientSession() as session:
                url = f"{self.base_url}/evo-brm/1.2.0/person/identity"
                logger.info(f"[人员] 请求身份列表: {url}")
                
                async with session.get(url, headers=headers, ssl=False) as response:
                    if response.status != 200:
                        logger.error(f"[人员] 获取人员身份失败: {await response.text()}")
                        return []
                        
                    result = await response.json()
                    if not result.get("success"):
                        logger.error(f"[人员] 获取人员身份失败: {result}")
                        return []
                        
                    identities = []
                    for item in result.get("data", {}).get("value", []):
                        identity = PersonIdentity(
                            id=item["id"],
                            name=item["name"], 
                            description=item["description"],
                            valid_flag=item["validFlag"]
                        )
                        identities.append(identity)
                    logger.info(f"[人员] 成功获取 {len(identities)} 个身份")
                    return identities
                    
        except Exception as e:
            logger.exception(f"[人员] 获取人员身份异常: {str(e)}")
            return []

    async def get_departments(self) -> List[Department]:
        """获取部门树形结构"""
        try:
            headers = await platform_auth.get_dahua_headers()
            async with aiohttp.ClientSession() as session:
                url = f"{self.base_url}/evo-brm/1.2.0/department/tree"
                data = {"needCheckDepartmentIdList": []}
                logger.info(f"[人员] 请求部门列表: {url}")
                
                async with session.post(url, headers=headers, json=data, ssl=False) as response:
                    if response.status != 200:
                        logger.error(f"[人员] 获取部门列表失败: {await response.text()}")
                        return []
                        
                    result = await response.json()
                    if not result.get("success"):
                        logger.error(f"[人员] 获取部门列表失败: {result}")
                        return []
                        
                    departments = []
                    for item in result.get("data", {}).get("value", []):
                        department = Department(
                            id=item["id"],
                            parent_id=item["parentId"],
                            name=item["name"],
                            name_ext=item["nameExt"], 
                            check_stat=item["checkStat"],
                            sort=item["sort"],
                            is_parent=item["isParent"],
                            parent_ids=item.get("parentIds"),
                            node_type=item.get("nodeType")
                        )
                        departments.append(department)
                    logger.info(f"[人员] 成功获取 {len(departments)} 个部门")
                    return departments
                    
        except Exception as e:
            logger.exception(f"[人员] 列表异常: {str(e)}")
            return []

    async def check_paper_number(self, paper_number: str) -> dict:
        """检查身份证号是否重复"""
        try:
            headers = await platform_auth.get_dahua_headers()
            async with aiohttp.ClientSession() as session:
                url = f"{self.base_url}/evo-brm/1.2.0/person/recycle/paper"
                params = {
                    "paperType": 111,  # 身份证类型
                    "paperNumber": paper_number
                }
                async with session.get(url, headers=headers, params=params, ssl=False) as response:
                    return await response.json()
        except Exception as e:
            logger.exception(f"检查身份证号异常: {str(e)}")
            return {"success": False, "errMsg": "网络请求异常"}

    async def create_person(self, person_data: dict) -> dict:
        """创建人员信息"""
        try:
            headers = await platform_auth.get_dahua_headers()
            async with aiohttp.ClientSession() as session:
                url = f"{self.base_url}/evo-brm/1.2.0/person"
                async with session.post(url, headers=headers, json=person_data, ssl=False) as response:
                    return await response.json()
        except Exception as e:
            logger.exception(f"创建人员信息异常: {str(e)}")
            return {"success": False, "errMsg": "网络请求异常"}

    async def get_person_detail(self, person_id: int) -> dict:
        """获取人员详情"""
        try:
            headers = await platform_auth.get_dahua_headers()
            async with aiohttp.ClientSession() as session:
                url = f"{self.base_url}/evo-brm/1.2.0/person/{person_id}"
                async with session.get(url, headers=headers, ssl=False) as response:
                    result = await response.json()
                    if result.get("success"):
                        return result.get("data")
                    return None
        except Exception as e:
            logger.exception(f"获取人员详情异常: {str(e)}")
            return None

class AsyncHelper(QThread):
    finished = pyqtSignal()
    data_loaded = pyqtSignal(object)
    
    def __init__(self, coro):
        super().__init__()
        self.coro = coro
        self._is_running = True
        self.loop = None
        
    def run(self):
        try:
            if self._is_running:
                # 创建新的事件循环
                self.loop = asyncio.new_event_loop()
                asyncio.set_event_loop(self.loop)
                
                # 运行协程
                result = self.loop.run_until_complete(self.coro)
                
                if self._is_running:
                    self.data_loaded.emit(result)
        except Exception as e:
            logger.exception("AsyncHelper error: %s", str(e))
        finally:
            if self._is_running:
                self.finished.emit()
            if self.loop:
                self.loop.close()
    
    def stop(self):
        """停止线程"""
        self._is_running = False
        if self.loop and self.loop.is_running():
            self.loop.stop()
        self.wait()

class InfoInputPage(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.person_api = PersonApi()
        # 创建 RFIDHelper 实例
        self.rfid_helper = RFIDHelper()
        self.setup_ui()
        self.current_tasks = []
        
        # 使用 QTimer.singleShot 来延迟加载数据
        QTimer.singleShot(0, self.start_loading)

    def create_required_label(self, text):
        """创建带红色星号的必填项标签"""
        label = QLabel(f"{text} <font color='red'>*</font>")
        return label

    def setup_ui(self):
        layout = QVBoxLayout(self)
        
        # 标题
        title = QLabel("人员信息录入")
        title.setStyleSheet("font-size: 24px; margin: 20px;")
        layout.addWidget(title)

        # 创建表单布局
        form_layout = QHBoxLayout()  # 左右布局
        left_layout = QVBoxLayout()
        right_layout = QVBoxLayout()
        
        # 左侧表单项
        # 姓名 (必填)
        name_layout = QHBoxLayout()
        name_label = self.create_required_label("姓名:")
        self.name_input = QLineEdit()
        self.name_input.setPlaceholderText("请输入姓名")
        name_layout.addWidget(name_label)
        name_layout.addWidget(self.name_input)
        left_layout.addLayout(name_layout)

        # 所属部门 (必填)
        dept_layout = QHBoxLayout()
        dept_label = self.create_required_label("所属部门:")
        
        # 创建一个垂直布局来包含显示框和树形控件
        dept_container = QVBoxLayout()
        
        # 添加显示框
        self.dept_display = QLineEdit()
        self.dept_display.setReadOnly(True)
        self.dept_display.setPlaceholderText("请选择部门")
        
        # 创建树形控件
        self.dept_tree = QTreeWidget()
        self.dept_tree.setHeaderLabel("部门列表")
        self.init_department_tree()
        self.dept_tree.itemClicked.connect(self.on_department_selected)
        
        # 将显示框和树形控件添加到垂直布局中
        dept_container.addWidget(self.dept_display)
        dept_container.addWidget(self.dept_tree)
        
        dept_layout.addWidget(dept_label)
        dept_layout.addLayout(dept_container)
        left_layout.addLayout(dept_layout)

        # 身份证号 (必填)
        id_layout = QHBoxLayout()
        id_label = self.create_required_label("身份证号:")
        self.id_input = QLineEdit()
        self.id_input.setPlaceholderText("请输入身份证号")
        self.id_input.textChanged.connect(self.on_id_input_changed)
        self.id_input.editingFinished.connect(self.on_id_input_finished)
        id_layout.addWidget(id_label)
        id_layout.addWidget(self.id_input)
        left_layout.addLayout(id_layout)

        # 自动识别字段组
        auto_group = QGroupBox("身份证信息")
        auto_layout = QGridLayout()
        self.birthday_label = QLabel("出生日期: ")
        self.gender_label = QLabel("性别: ")
        self.age_label = QLabel("年龄: ")
        auto_layout.addWidget(self.birthday_label, 0, 0)
        auto_layout.addWidget(self.gender_label, 0, 1)
        auto_layout.addWidget(self.age_label, 0, 2)
        auto_group.setLayout(auto_layout)
        left_layout.addWidget(auto_group)

        # 右侧表单项
        # 人员身份 (必填)
        identity_layout = QHBoxLayout()
        identity_label = self.create_required_label("人员身份:")
        self.identity_combo = QComboBox()
        identity_layout.addWidget(identity_label)
        identity_layout.addWidget(self.identity_combo)
        right_layout.addLayout(identity_layout)

        # 手机号
        phone_layout = QHBoxLayout()
        phone_label = QLabel("手机号:")
        self.phone_input = QLineEdit()
        self.phone_input.setPlaceholderText("请输入手机号(选填)")
        self.phone_input.textChanged.connect(self.validate_phone)
        phone_layout.addWidget(phone_label)
        phone_layout.addWidget(self.phone_input)
        right_layout.addLayout(phone_layout)

        # 权限有效期 (必填)
        date_layout = QHBoxLayout()
        date_label = self.create_required_label("权限有效期:")
        self.date_start = QDateTimeEdit()
        self.date_end = QDateTimeEdit()
        date_layout.addWidget(date_label)
        date_layout.addWidget(self.date_start)
        date_layout.addWidget(QLabel("至"))
        date_layout.addWidget(self.date_end)
        right_layout.addLayout(date_layout)

        # 人员卡号 (必填)
        card_layout = QHBoxLayout()
        card_label = self.create_required_label("人员卡号:")
        self.card_input = QLineEdit()
        self.card_input.setPlaceholderText("请输入卡号")
        self.card_input.setMaxLength(6)  # 限制最大长度为6位
        self.card_input.textChanged.connect(self.validate_card_number)  # 添加验证
        self.card_input.textChanged.connect(self.update_user_number)
        card_layout.addWidget(card_label)
        card_layout.addWidget(self.card_input)
        right_layout.addLayout(card_layout)

        # 人员编号
        number_layout = QHBoxLayout()
        number_label = QLabel("人员编号:")
        self.number_input = QLineEdit()
        number_layout.addWidget(number_label)
        number_layout.addWidget(self.number_input)
        right_layout.addLayout(number_layout)

        # 主副卡选择
        card_type_layout = QHBoxLayout()
        card_type_label = QLabel("卡片类型:")
        self.card_type_group = QButtonGroup()
        self.main_card_radio = QRadioButton("主卡")
        self.sub_card_radio = QRadioButton("副卡")
        self.main_card_radio.setChecked(True)
        self.card_type_group.addButton(self.main_card_radio)
        self.card_type_group.addButton(self.sub_card_radio)
        self.main_card_radio.toggled.connect(self.on_card_type_changed)
        card_type_layout.addWidget(card_type_label)
        card_type_layout.addWidget(self.main_card_radio)
        card_type_layout.addWidget(self.sub_card_radio)
        right_layout.addLayout(card_type_layout)

        # 添加左右布局到表单布局
        form_layout.addLayout(left_layout)
        form_layout.addLayout(right_layout)
        
        # 添加表单布局到主布局
        layout.addLayout(form_layout)

        # 添加按钮
        button_layout = QHBoxLayout()
        save_btn = QPushButton("保存")
        save_btn.clicked.connect(self.save_info)
        cancel_btn = QPushButton("返回")
        cancel_btn.clicked.connect(self.go_back)
        button_layout.addWidget(save_btn)
        button_layout.addWidget(cancel_btn)
        layout.addLayout(button_layout)

        # 添加弹性空间
        layout.addStretch()

    def init_department_tree(self):
        """初始化部门树形结构"""
        self.dept_tree.setHeaderLabel("部门列表")
        self.dept_tree.setMinimumHeight(200)  # 增加树形控件的高度
        self.dept_tree.setSelectionMode(QTreeWidget.SelectionMode.SingleSelection)

    def on_department_selected(self, item: QTreeWidgetItem, column: int):
        """当部门被选中时更新显示框"""
        dept_id = item.data(0, Qt.ItemDataRole.UserRole)
        dept_name = item.text(0)
        
        # 获取完整的部门路径名称
        path_names = []
        current_item = item
        while current_item is not None:
            path_names.insert(0, current_item.text(0))
            current_item = current_item.parent()
        
        # 更新显示框
        self.dept_display.setText(" / ".join(path_names))

    def get_selected_department(self) -> Optional[tuple]:
        """获取选中的部门
        Returns:
            tuple: (部门ID, 部门名称) 或 None
        """
        selected_items = self.dept_tree.selectedItems()
        if selected_items:
            item = selected_items[0]
            dept_id = item.data(0, Qt.ItemDataRole.UserRole)
            dept_name = item.text(0)
            return (dept_id, dept_name)
        return None

    def update_auto_fields(self):
        """根据身份证号更新自动识别字段"""
        id_number = self.id_input.text()
        if len(id_number) == 18:
            # 解析身份证信息
            birth_year = id_number[6:10]
            birth_month = id_number[10:12]
            birth_day = id_number[12:14]
            gender_code = int(id_number[-2])
            
            # 更新显示
            self.birthday_label.setText(f"出生日期: {birth_year}-{birth_month}-{birth_day}")
            self.gender_label.setText(f"性别: {'男' if gender_code % 2 == 1 else '女'}")
            
            # 计算年龄
            current_year = QDate.currentDate().year()
            age = current_year - int(birth_year)
            self.age_label.setText(f"年龄: {age}岁")

    def update_user_number(self):
        """根据卡号更新人员编号"""
        card_number = self.card_input.text()
        if card_number.isdigit():
            self.number_input.setText(f"L{card_number}")

    def on_card_type_changed(self, checked):
        """当卡片类型改变时处理姓名"""
        if checked:  # 选中主卡
            current_name = self.name_input.text().strip()
            if current_name and not current_name.endswith('-'):
                self.name_input.setText(f"{current_name}-")
        else:  # 选中副卡
            current_name = self.name_input.text().strip()
            if current_name.endswith('-'):
                self.name_input.setText(current_name[:-1])

    def validate_id_number(self, id_number: str) -> Tuple[bool, str]:
        """验证身份证号
        Returns:
            tuple: (是否有效, 错误信息)
        """
        if not id_number:
            return False, "身份证号不能为空"
        
        if len(id_number) != 18:
            return False, "身份证号必须是18位"
        
        # 检查前17位是否都是数字
        if not id_number[:-1].isdigit():
            return False, "身份证号前17位必须是数字"
        
        # 检查最后一位是否是数字或X
        if not (id_number[-1].isdigit() or id_number[-1].upper() == 'X'):
            return False, "身份证号最后一位必须是数字或X"
        
        # 验证出生日期
        try:
            year = int(id_number[6:10])
            month = int(id_number[10:12])
            day = int(id_number[12:14])
            
            # 检查年份范围 (假设1900年到当前年份都是有效的)
            current_year = datetime.now().year
            if year < 1900 or year > current_year:
                return False, "出生年份无效"
            
            # 检查月份
            if month < 1 or month > 12:
                return False, "出生月份无效"
            
            # 检查日期
            import calendar
            if day < 1 or day > calendar.monthrange(year, month)[1]:
                return False, "出生日期无效"
            
        except ValueError:
            return False, "出生日期格式错误"
        
        # 校验码验证
        factor = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
        check_code = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2']
        
        sum = 0
        for i in range(17):
            sum += int(id_number[i]) * factor[i]
        
        if check_code[sum % 11] != id_number[-1].upper():
            return False, "校验码错误"
        
        return True, ""

    def on_id_input_changed(self):
        """身份证号输入变化时的处理"""
        id_number = self.id_input.text().strip()
        if len(id_number) == 18:  # 只在输入完整时验证
            is_valid, error_msg = self.validate_id_number(id_number)
            if not is_valid:
                self.id_input.setStyleSheet("border: 1px solid red;")
                self.id_input.setToolTip(error_msg)
                # 清空自动识别字段
                self.birthday_label.setText("出生日期: ")
                self.gender_label.setText("性别: ")
                self.age_label.setText("年龄: ")
            else:
                self.id_input.setStyleSheet("")
                self.id_input.setToolTip("")
                # 更新自动识别字段
                self.update_auto_fields()
        else:
            self.id_input.setStyleSheet("")
            self.id_input.setToolTip("")

    def on_id_input_finished(self):
        """身份证输入完成时的处理"""
        paper_number = self.id_input.text().strip()
        if not paper_number:
            return
        
        # 先进行格式验证
        is_valid, error_msg = self.validate_id_number(paper_number)
        if not is_valid:
            QMessageBox.warning(self, "警告", error_msg)
            self.id_input.setFocus()
            return
        
        # 验证通过后再检查重复
        if len(paper_number) == 18:
            async_helper = AsyncHelper(self.person_api.check_paper_number(paper_number))
            async_helper.data_loaded.connect(self.on_paper_number_checked)
            self.current_tasks.append(async_helper)
            async_helper.finished.connect(lambda: self.current_tasks.remove(async_helper))
            async_helper.start()

    def on_paper_number_checked(self, result):
        """身份证号检查完成的回调"""
        if not result.get("success"):
            QMessageBox.warning(self, "警告", result.get("errMsg", "身份证号验证失败"))
            self.id_input.setFocus() 

    def validate_card_number(self, text):
        """验证卡号格式"""
        # 移除非数字字符
        numbers_only = ''.join(filter(str.isdigit, text))
        
        # 如果输入的内容与过滤后的不同，说明包含非数字字符
        if text != numbers_only:
            self.card_input.setText(numbers_only)
            return
            
        # 设置样式提示
        if not numbers_only:
            self.card_input.setStyleSheet("")
            self.card_input.setToolTip("")
        elif len(numbers_only) > 6:
            self.card_input.setStyleSheet("border: 1px solid red;")
            self.card_input.setToolTip("卡号不能超过6位")
        else:
            self.card_input.setStyleSheet("")
            self.card_input.setToolTip("")

    def save_info(self):
        """保存信息"""
        # 检查必填项
        if not self.name_input.text().strip():
            QMessageBox.warning(self, "警告", "请输入姓名")
            return

        selected_dept = self.get_selected_department()
        if not selected_dept:
            QMessageBox.warning(self, "警告", "请选择所属部门")
            return
        
        dept_id, dept_name = selected_dept

        # 获取选中的身份ID
        identity_id = self.identity_combo.currentData()
        if identity_id is None:
            QMessageBox.warning(self, "警告", "请选择人员身份")
            return

        if not self.id_input.text().strip():
            QMessageBox.warning(self, "警告", "请输入身份证号")
            return

        if not self.card_input.text().strip():
            QMessageBox.warning(self, "警告", "请输入人员卡号")
            return

        if not self.date_start.dateTime().isValid() or not self.date_end.dateTime().isValid():
            QMessageBox.warning(self, "警告", "请设置有效的权限有效期")
            return
            
        if not self.validate_phone():
            QMessageBox.warning(self, "警告", "请输入正确的手机号格式")
            return
            
        # 添加身份证验证
        is_valid, error_msg = self.validate_id_number(self.id_input.text().strip())
        if not is_valid:
            QMessageBox.warning(self, "警告", error_msg)
            self.id_input.setFocus()
            return
        
        card_number = self.card_input.text().strip()
        if not card_number:
            QMessageBox.warning(self, "警告", "请输入人员卡号")
            return
        if not card_number.isdigit():
            QMessageBox.warning(self, "警告", "卡号必须是数字")
            return
        if len(card_number) > 6:
            QMessageBox.warning(self, "警告", "卡号不能超过6位")
            return

        # 先写入 RFID 卡
        if not self.write_to_rfid(card_number):
            QMessageBox.warning(self, "错误", "写入RFID卡失败，请确保卡片在读写范围内")
            return

        # 构建保存数据
        person_data = {
            "name": self.name_input.text().strip(),
            "departmentName": dept_name,
            "code": self.number_input.text().strip(),
            "paperType": 111,  # 身份证
            "paperNumber": self.id_input.text().strip(),
            "sex": 1 if self.gender_label.text().endswith("男") else 2,
            "birthday": self.birthday_label.text().split(": ")[1],
            "personIdentityId": identity_id,
            "age": int(self.age_label.text().split(": ")[1][:-1]),
            "nation": 1,  # 默认汉族
            "country": "CHN",
            "personType": "0",
            "isAdmin": 0,
            "departmentId": dept_id,
            "departmentList": [{
                "departmentId": dept_id,
                "departmentType": 1,
                "departmentName": dept_name
            }],
            "validStartTime": self.date_start.dateTime().toString("yyyy-MM-dd hh:mm:ss"),
            "validEndTime": self.date_end.dateTime().toString("yyyy-MM-dd hh:mm:ss"),
            "cards": [{
                "cardNumber": self.card_input.text().strip(),
                "category": "0" if self.main_card_radio.isChecked() else "1",
                "startDate": self.date_start.dateTime().toString("yyyy-MM-dd hh:mm:ss"),
                "endDate": self.date_end.dateTime().toString("yyyy-MM-dd hh:mm:ss"),
                "isMainCard": 1 if self.main_card_radio.isChecked() else 0,
                "isCoercion": 0
            }],
            "status": 1
        }
        
        # 如果有手机号，添加到数据中
        if self.phone_input.text().strip():
            person_data["phone"] = self.phone_input.text().strip()
        
        # 调用保存接口
        async_helper = AsyncHelper(self.person_api.create_person(person_data))
        async_helper.data_loaded.connect(self.on_save_completed)
        self.current_tasks.append(async_helper)
        async_helper.finished.connect(lambda: self.current_tasks.remove(async_helper))
        async_helper.start()

    def on_save_completed(self, result):
        """保存完成的回调"""
        if result.get("success"):
            QMessageBox.information(self, "提示", "保存成功")
            self.go_back()  # 保存成功后返回
        else:
            QMessageBox.warning(self, "错误", result.get("errMsg", "保存失败"))

    def go_back(self):
        """返回设备页面"""
        if self.parent():
            # 切换到设备页面(索引0)
            self.parent().switch_to_device_page()

    def on_data_loaded(self, data):
        """数据加载完成的回调"""
        identities, departments = data
        # 处理身份数据
        self.identity_combo.clear()
        for identity in identities:
            self.identity_combo.addItem(identity.name, identity.id)
            
        # 处理部门数据
        self.update_department_tree(departments)

    def update_department_tree(self, departments: List[Department]):
        """更新部门树"""
        self.dept_tree.clear()
        
        # 创建部门ID到节点的映射
        dept_nodes = {}
        
        # 第一遍循环创建所有节点
        for dept in departments:
            item = QTreeWidgetItem()
            item.setText(0, dept.name)
            item.setData(0, Qt.ItemDataRole.UserRole, dept.id)  # 存储部门ID
            dept_nodes[dept.id] = item
            
            # 所有节点都可选
            item.setFlags(item.flags() | Qt.ItemFlag.ItemIsSelectable)
        
        # 第二遍循环构建树形结构
        for dept in departments:
            if dept.parent_id == 0:  # 根节点
                self.dept_tree.addTopLevelItem(dept_nodes[dept.id])
            else:  # 子节点
                if dept.parent_id in dept_nodes:
                    parent_node = dept_nodes[dept.parent_id]
                    parent_node.addChild(dept_nodes[dept.id])
        
        # 展开所有节点
        self.dept_tree.expandAll()

    def start_loading(self):
        """开始加载数据"""
        loop = asyncio.get_event_loop()
        loop.create_task(self.load_data())

    async def load_data(self):
        """异步加载数据"""
        try:
            identities = await self.person_api.get_person_identities()
            departments = await self.person_api.get_departments()
            self.on_data_loaded((identities, departments))
        except Exception as e:
            logger.exception("加载初始数据失败")
            self.on_data_loaded(([], []))

    def validate_phone(self):
        """验证手机号格式"""
        phone = self.phone_input.text().strip()
        if phone:  # 如果有输入才验证
            pattern = r'^1[3-9]\d{9}$'
            if not re.match(pattern, phone):
                self.phone_input.setStyleSheet("border: 1px solid red;")
                return False
            else:
                self.phone_input.setStyleSheet("")
                return True
        else:
            self.phone_input.setStyleSheet("")
            return True  # 空值也返回True因为是选填 

    def closeEvent(self, event):
        """窗口关闭时清理"""
        for task in self.current_tasks[:]:
            task.stop()
        self.current_tasks.clear()
        super().closeEvent(event)

    def set_person_info(self, person_info: dict):
        """设置人员信息"""
        # 基本信息
        self.name_input.setText(person_info.get('name', ''))
        self.id_input.setText(person_info.get('paperNumber', ''))
        self.phone_input.setText(person_info.get('phone', ''))
        self.number_input.setText(person_info.get('code', ''))
        
        # 设置部门
        dept_id = person_info.get('departmentId')
        dept_name = person_info.get('departmentName', '')
        self.select_department(dept_id)
        
        # 设置身份
        identity_id = person_info.get('personIdentityId')
        self.select_identity(identity_id)
        
        # 设置有效期
        start_time = person_info.get('validStartTime', '')
        end_time = person_info.get('validEndTime', '')
        if start_time:
            self.date_start.setDateTime(QDateTime.fromString(start_time, "yyyy-MM-dd hh:mm:ss"))
        if end_time:
            self.date_end.setDateTime(QDateTime.fromString(end_time, "yyyy-MM-dd hh:mm:ss"))
            
        # 设置卡片信息
        cards = person_info.get('cards', [])
        if cards:
            main_card = next((card for card in cards if card.get('isMainCard') == 1), None)
            if main_card:
                self.card_input.setText(main_card.get('cardNumber', ''))
                self.main_card_radio.setChecked(True)
            else:
                sub_card = next((card for card in cards if card.get('isMainCard') == 0), None)
                if sub_card:
                    self.card_input.setText(sub_card.get('cardNumber', ''))
                    self.sub_card_radio.setChecked(True)
                    
        # 更新自动识别字段
        self.update_auto_fields()

    def select_department(self, dept_id):
        """选择指定的部门"""
        def find_and_select_dept(item):
            item_id = item.data(0, Qt.ItemDataRole.UserRole)
            if item_id == dept_id:
                self.dept_tree.setCurrentItem(item)
                return True
            for i in range(item.childCount()):
                if find_and_select_dept(item.child(i)):
                    return True
            return False
            
        # 遍历所有顶级节点
        for i in range(self.dept_tree.topLevelItemCount()):
            if find_and_select_dept(self.dept_tree.topLevelItem(i)):
                break

    def select_identity(self, identity_id):
        """选择指定的身份"""
        for i in range(self.identity_combo.count()):
            if self.identity_combo.itemData(i) == identity_id:
                self.identity_combo.setCurrentIndex(i)
                break 

    def write_to_rfid(self, card_number):
        try:
            # 将write_data改为write_tag
            success = self.rfid_helper.write_tag(
                card_number
            )
            print(success)
            return success
        except Exception as e:
            logger.error(f"写入RFID卡异常: {e}")
            return False 